/*
Pyxis 2.0
Copyright 2010-2011 Thomas W. Holtquist

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

using System;
using System.Threading;

using Microsoft.SPOT;
using Microsoft.SPOT.Touch;

namespace Skewworks.Pyxis.Kernel
{

    internal class InputManager : MarshalByRefObject
    {

        #region Variables

        private PyxisAPI api;
        private Thread myTouch;
        private bool _penDown;          // Pen Down when TRUE
        private int _x;
        private int _y;
        private int _lastX;
        private int _lastY;
        private int _maxX;
        private int _maxY;

        private bool _bVirtKey = true;

        private TouchConnection _touch;

        #endregion

        #region Constructor

        public InputManager(PyxisAPI API, int MaxX, int MaxY)
        {
            api = API;
            _maxX = MaxX;
            _maxY = MaxY;

            _touch = new TouchConnection();
            Touch.Initialize(_touch);
            TouchCollectorConfiguration.CollectionMode = CollectionMode.GestureOnly;
            TouchCollectorConfiguration.CollectionMethod = CollectionMethod.Native;

            myTouch = new Thread(myTouch_Tick);
            myTouch.Priority = ThreadPriority.Highest;
            myTouch.Start();
        }

        #endregion

        #region Properties

        public bool UseVirtualKeyboard
        {
            get { return _bVirtKey; }
        }

        #endregion

        #region Internal Methods

        internal TouchEventArgs getTouchPoint()
        {
            while (true)
            {
                // Check the Pen
                int x = 0;
                int y = 0;
                TouchCollectorConfiguration.GetLastTouchPoint(ref x, ref y);

                if (x != 1022 && x > 0 || y != 1022 && y > 0)
                {
                    _x = x;
                    _y = y;

                    // Pen down
                    if (!_penDown)
                    {
                        // Pen Down
                        _penDown = true;
                        _lastX = x;
                        _lastY = y;
                        return new TouchEventArgs(new point(x, y), 0);
                    }
                }
                else
                {
                    if (_penDown)
                    {
                        // Pen Tapped
                        _penDown = false;
                        return new TouchEventArgs(new point(_lastX, _lastY), 1);
                    }
                }

                Thread.Sleep(5);
            }
        }

        internal void Pause()
        {
            myTouch.Suspend();
        }

        internal void Reset()
        {
            try
            {
                myTouch.Suspend();
                myTouch = null;
            }
            catch (Exception) { }

            myTouch = new Thread(myTouch_Tick);
            myTouch.Priority = ThreadPriority.Highest;
            myTouch.Start();
        }

        internal void Resume()
        {
            myTouch.Resume();
        }

        #endregion

        #region Private Methods

        void myTouch_Tick()
        {
            int x = 0;
            int y = 0;
            bool bIgnore = false;
            point ptLast;

            while (true)
            {
                // Check the Pen
                TouchCollectorConfiguration.GetLastTouchPoint(ref x, ref y);
                bIgnore = false;

                if (x != 1022 && x > 0 || y != 1022 && y > 0)
                {
                    _x = x;
                    _y = y;

                    // Pen down
                    if (_penDown)
                    {
                        // We already know about it
                        if (System.Math.Abs(_lastX - x) + System.Math.Abs(_lastY - y) > 10)
                        {
                            _lastX = x;
                            _lastY = y;
                            ptLast = new point(x, y);

                            if (api._ActiveCM != null)
                                api._ActiveCM.TouchMove(null, ptLast);
                            else if (api._ActiveForm != null)
                                api._ActiveForm.TouchMove(null, ptLast);
                        }
                    }
                    else
                    {
                        // Pen Down
                        _penDown = true;
                        _lastX = x;
                        _lastY = y;
                        ptLast = new point(x, y);

                        if (api.desktop != null)
                            if (api.desktop._mnu.InvokeTouchDown(ptLast)) 
                                bIgnore = true;

                        if (!bIgnore)
                        {

                            if (api._ActiveCM != null)
                            {
                                if (!api._ActiveCM.InvokeTouchDown(ptLast))
                                    api.HideContextMenu();
                            }
                            else if (api._ActiveForm != null)
                                api.ActiveForm.TouchDown(null, ptLast);
                            else if (api.desktop != null)
                                api.desktop.TouchDown(null, ptLast);
                            else
                                api.RaiseUnhandledTouch(true, ptLast);
                        }
                    }
                }
                else
                {
                    if (_penDown)
                    {
                        // Pen Tapped
                        _penDown = false;
                        ptLast = new point(_lastX, _lastY);

                        if (api.desktop != null)
                            if (api.desktop._mnu.InvokeTouchUp(ptLast)) 
                                bIgnore = true;

                        if (!bIgnore)
                        {
                            if (api._ActiveCM != null)
                                api._ActiveCM.InvokeTouchUp(ptLast);
                            else if (api._ActiveForm != null)
                                api.ActiveForm.TouchUp(null, ptLast);
                            else if (api.desktop != null)
                                api.desktop.TouchUp(null, ptLast);
                            else
                                api.RaiseUnhandledTouch(false, ptLast);
                        }
                    }
                }

                Thread.Sleep(5);
            }
        }

        #endregion

    }

    internal class TouchConnection : IEventListener
    {

        public void InitializeForEventSource() { }

        public bool OnEvent(BaseEvent baseEvent)
        {
            return true;
        }

    }

}
